package com.atguigu.gmall.gateway.filter;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.common.result.ResultCodeEnum;
import com.atguigu.gmall.common.util.IpUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

/**
 * 自定义全局过滤器
 * <p>
 * 首先： 在网关  默认开启 9大过滤器
 * 自定义了第10个过滤器
 * -2147483647 负整数最大  ~ -1~ 0  ~  正整数最大  2147483647
 * 优先执行                         最后执行
 */
//@Order(2147483647)
@Component
public class LoginGlobalFilter implements GlobalFilter, Ordered {

    @Autowired
    private RedisTemplate redisTemplate;
    //去登录页面的路径
    private final static String LOGIN_URL = "http://passport.gmall.com/login.html?originUrl=";

    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    //同步需要登录的路径
    @Value("${auth.urls}")
    private String[] authUrls;

    //全局过滤器 执行方法
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();

        //0:获取请求URL
        String path = request.getPath().toString();

        //1:当前请求判断是否需要登录
        // （首页 、搜索 、详情）不登录
        // 购物车（可登录、可不登录）
        // （结算 提交订单 支付）必须登录  /*/auth/**  swagger2  异步的
        //  商品微服务  /*/product/**   VUE ajax  异步
        //  用户微服务 /*/user/**          ajax  异步
        //2:判断用户是否登录  取决于cookie 是否有token 令牌
        String userId = getUserId(request);
        System.out.println(userId);



        if(antPathMatcher.match("/**/auth/**",path)){
            //匹配成功 需要登录
            if(StringUtils.isEmpty(userId)){
                //未登录  处理结果  异步情况  function(data) { result.code=208 result.message=未登录
                return out(response,ResultCodeEnum.LOGIN_AUTH);
            }
        }
        //3:当前请求是同步 结算页面 trade.html  pay.html
        for (String authUrl : authUrls) {
            if(path.indexOf(authUrl) != -1 && StringUtils.isEmpty(userId)){
                //存在了  并 未登录
                try {
                    //让浏览器知道要重定向
                    response.setStatusCode(HttpStatus.SEE_OTHER); //303
                //重定向到登录页面  响应头
                    response.getHeaders().add(
                            HttpHeaders.LOCATION,LOGIN_URL +
                                    URLEncoder.encode(request.getURI().getRawSchemeSpecificPart(),"utf-8"));
                    return response.setComplete();
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
//   //list.gmall.com/list.html?keyword=手机。。
            }
        }
        //4:当前请求资源是否为内部资源   /**/inner/**
        if(antPathMatcher.match("/**/inner/**",path)){
            //不管登录  就不行
            return out(response,ResultCodeEnum.PERMISSION);
        }
        //5:传递用户ID到后面微服务                 后面微服务还要传递后面的微服务
        //request.getHeaders().add("k","v");
        //报错： 不允许修改之前的request对象  浏览器Http请求  Tomcat服务器
        if(!StringUtils.isEmpty(userId)){
            request.mutate().header("userId",userId);
        }
        //临时用户ID
        String userTempId = getUserTempId(request);
        if(!StringUtils.isEmpty(userTempId)){
            request.mutate().header("userTempId",userTempId);
        }
        return chain.filter(exchange);
    }

    //异步结果处理
    private Mono<Void> out(ServerHttpResponse response,ResultCodeEnum resultCodeEnum) {
        byte[] bytes = new byte[0];
        try {
            bytes = JSONObject.toJSONString(
                    Result.build(null,resultCodeEnum)).
                    getBytes("utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        DataBufferFactory dataBufferFactory = response.bufferFactory();
        DataBuffer dataBuffer = dataBufferFactory.wrap(bytes);
        //设置response的编码  Content-Type: text/html;charset=UTF-8
        response.getHeaders().add(
                HttpHeaders.CONTENT_TYPE,"application/json;charset=UTF-8");
        return response.writeWith(Mono.just(dataBuffer));
    }


    //获取用户id
    private String getUserId(ServerHttpRequest request) {
        //1:先获取请求头中的token
        String token = request.getHeaders().getFirst("token");
        if (StringUtils.isEmpty(token)) {
            //2:没有 再从Cookie中获取token
            HttpCookie httpCookie = request.getCookies().getFirst("token");
            if (null != httpCookie) {
                token = httpCookie.getValue();
            }
        }
        if (!StringUtils.isEmpty(token)) {
            //3:有命牌 再判断ip
            //判断IP
            HttpCookie httpCookie = request.getCookies().getFirst("ip");
            if(null != httpCookie){
                String ip = httpCookie.getValue();
                if(!StringUtils.isEmpty(ip)){
                    //当前请求的IP比对
                    String gatwayIpAddress = IpUtil.getGatwayIpAddress(request);
                    System.out.println(gatwayIpAddress);
                    if(gatwayIpAddress.equals("127.0.0.1") ||  gatwayIpAddress.equals(ip)){
                        // 直接去Redis中查询用户ID
                        if (redisTemplate.hasKey("user:login:" + token)) {
                            return (String) redisTemplate.opsForValue().get("user:login:" + token);
                        }
                    }
                }
            }else{
                String ip = request.getHeaders().getFirst("ip");
                if(!StringUtils.isEmpty(ip)){
                    //当前请求的IP比对
                    String gatwayIpAddress = IpUtil.getGatwayIpAddress(request);
                    System.out.println(gatwayIpAddress);
                    if(gatwayIpAddress.equals("127.0.0.1") ||  gatwayIpAddress.equals(ip)){
                        // 直接去Redis中查询用户ID
                        if (redisTemplate.hasKey("user:login:" + token)) {
                            return (String) redisTemplate.opsForValue().get("user:login:" + token);
                        }
                    }
                }
            }
        }
        //4:没有 null
        return null;
    }
    //获取临时用户ID
    private String getUserTempId(ServerHttpRequest request) {
        //1:先获取请求头中的token
        String userTempId = request.getHeaders().getFirst("userTempId");
        if (StringUtils.isEmpty(userTempId)) {
            //2:没有 再从Cookie中获取token
            HttpCookie httpCookie = request.getCookies().getFirst("userTempId");
            if (null != httpCookie) {
                userTempId = httpCookie.getValue();
            }
        }
        return userTempId;
    }


    //排序
    @Override
    public int getOrder() {
        return 0;
    }
}
